package org.cogaen.sound;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @class FilteredSoundStream
 * @author Florian Lettner
 *
 * Represents an audio stream with a filter applied.
 */
public class FilteredSoundStream extends FilterInputStream {
	/** Indicates that the remaining size is unknown. */
	private static final int REMAINING_SIZE_UNKNOWN = -1;
	
	/** The sound filter to be applied. */
	private SoundFilter soundFilter;
	
	/** The remaining size of the stream. */
	private int remainingSize;

	/**
	 * Creates a new filtered sound stream.
	 * 
	 * @param in The input stream used for filtering.
	 * @param soundFilter The filter to be applied.
	 */
	public FilteredSoundStream(InputStream in, SoundFilter soundFilter) {
		super(in);
		this.soundFilter = soundFilter;
		remainingSize = REMAINING_SIZE_UNKNOWN;
	}

	/**
	 * Processed the filtered sound stream.
	 * 
	 * @param sampledata The sample data to be read.
	 * @param offset The offset to be applied.
	 * @param length The length of the stream.
	 */
	@Override
	public int read(byte[] sampledata, int offset, int length)
			throws IOException {
		int bytesRead = super.read(sampledata, offset, length);
		if (bytesRead > 0) {
			soundFilter.filter(sampledata, offset, bytesRead);
			return bytesRead;
		}
		if (remainingSize == REMAINING_SIZE_UNKNOWN) {
			remainingSize = soundFilter.getRemainingSize();
			remainingSize = remainingSize / 4 * 4;
		}
		if (remainingSize > 0) {
			length = Math.min(length, remainingSize);
			for (int i = offset; i < offset + length; i++) {
				sampledata[i] = 0;
			}
			soundFilter.filter(sampledata, offset, length);
			remainingSize -= length;
			return length;
		} else {
			return REMAINING_SIZE_UNKNOWN;
		}
	}

}
